﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetFrameworkExtensions.PresentationLayer.Properties;
using NetFrameworkExtensions.Threading;

namespace NetFrameworkExtensions.PresentationLayer
{
  public class WindowContext : IWindowContext, IWindowContextInternal
  {
    private Guid? _windowGuid;
    private Guid? _parentGuid;

    public WindowContext()
    {
      UseGlobalSynchronizationContext = true;
    }

    public Guid? ParentGuid
    {
      get { return _parentGuid; }
      set
      {
        if (_parentGuid.HasValue && (value == null || _parentGuid.Value != value.Value))
          throw new InvalidOperationException(FormattedResources.ExCannotChangeWindowsIdOnceSet);
        _parentGuid = value;
      }
    }

    public Guid? WindowGuid
    {
      get { return _windowGuid; }
      set
      {
        if (_windowGuid.HasValue && (value == null || _windowGuid.Value != value.Value))
          throw new InvalidOperationException(FormattedResources.ExCannotChangeWindowsIdOnceSet);
        _windowGuid = value;
      }
    }

    public Action<bool> OnClose { get; set; }

    public bool UseGlobalSynchronizationContext { get; set; }

    public void CallOnClose(bool accept, bool remove = true)
    {
      if (OnClose != null)
      {
        if (UseGlobalSynchronizationContext)
          GlobalSynchronizationContext.Send(() => OnClose(accept));
        else
          OnClose(accept);
        if (remove)
          OnClose = null;
      }
    }

    public void Send(Action action)
    {
      if (action == null) throw new ArgumentNullException("action");
      if (UseGlobalSynchronizationContext)
        GlobalSynchronizationContext.Send(action);
      else
        action();
    }

    public void Send(Action<object> action, object state)
    {
      if (action == null) throw new ArgumentNullException("action");
      if (UseGlobalSynchronizationContext)
        GlobalSynchronizationContext.Send(() => action(state));
      else
        action(state);
    }

    public void Send<T>(Action<T> action, T state)
    {
      if (action == null) throw new ArgumentNullException("action");
      if (UseGlobalSynchronizationContext)
        GlobalSynchronizationContext.Send(() => action(state));
      else
        action(state);
    }

    public void Post(Action action)
    {
      if (action == null) throw new ArgumentNullException("action");
      if (UseGlobalSynchronizationContext)
        GlobalSynchronizationContext.Post(action);
      else
        action();
    }

    public void Post(Action<object> action, object state)
    {
      if (action == null) throw new ArgumentNullException("action");
      if (UseGlobalSynchronizationContext)
        GlobalSynchronizationContext.Post(() => action(state));
      else
        action(state);
    }

    public void Post<T>(Action<T> action, T state)
    {
      if (action == null) throw new ArgumentNullException("action");
      if (UseGlobalSynchronizationContext)
        GlobalSynchronizationContext.Post(() => action(state));
      else
        action(state);
    }

    void IWindowContextInternal.ChangeWindowGuid(Guid newGuid)
    {
      _windowGuid = newGuid;
    }

    public void ChangeParentGuid(Guid newGuid)
    {
      _parentGuid = newGuid;
    }

    public object ParentData { get; set; }

    public object WindowData { get; set; }
  }
}
